﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using DataAccessLayer;
using Editor.Properties;

namespace Editor
{
    /// <summary>
    /// Form which to configure a level with
    /// </summary>
    public sealed partial class LevelEditForm : Form
    {
        /// <summary>
        /// The level that will be configured.
        /// Set this object to any existing level.
        /// </summary>
        public GameLevel GameLevel;

        /// <summary>
        /// The enemies that are created in the editor
        /// </summary>
        public IList<Enemy> Enemies;

        /// <summary>
        /// Initializes a new instance of the <see cref="LevelEditForm"/> class.
        /// </summary>
        /// <param name="level">The level.</param>
        /// <param name="enemies">The enemies.</param>
        public LevelEditForm(GameLevel level, IList<Enemy> enemies)
        {
            InitializeComponent();

            InitLevel(level);

            InitEnemies(enemies);
        }

        private void InitLevel(GameLevel level)
        {
            GameLevel = level;

            lvlIdTxbx.Text = GameLevel.ID.ToString();

            lvlStartTimeTxbx.Text = GameLevel.StartTime.ToString();

            foreach (var wave in GameLevel.LevelWaves)
            {
                configWavesLv.Items.Add(new ListViewItem(new[]
                                                      {
                                                          wave.Id.ToString(),
                                                          wave.StartTime.ToString(),
                                                          wave.EnemySets.Count.ToString()
                                                      }));
            }
        }

        private void InitEnemies(IList<Enemy> enemies)
        {
            Enemies = enemies ?? new List<Enemy>();

            foreach (var enemy in Enemies)
            {
                //levelObjLv.Items.Add(new ListViewItem(new[]
                //                                      {
                //                                          "",
                //                                          enemy.ID.ToString(),
                //                                          enemy.Stats.Hp.ToString(),
                //                                          enemy.Stats.Power.ToString(),
                //                                          enemy.Stats.Speed.ToString(),
                //                                          enemy is MiniBossEnemy ? "Mini Boss" :
                //                                          (enemy is BossEnemy ? "Boss" : "Normal Enemy")
                //                                      }));
            }
        }

        private void configWavesLv_SelectedIndexChanged(object sender, EventArgs e)
        {
            bool goodSelection = configWavesLv.SelectedIndices.Count > 0;

            configWaveGbx.Enabled = goodSelection;

            if (!goodSelection) return;

            int index = configWavesLv.SelectedIndices[0];

            waveIdTxbx.Text = GameLevel.LevelWaves[index].Id.ToString();

            waveStartTimeTxbx.Text = GameLevel.LevelWaves[index].StartTime.ToString();

            waveEnemySpawnSetsLv.Items.Clear();

            foreach (var set in GameLevel.LevelWaves[index].EnemySets)
            {
                waveEnemySpawnSetsLv.Items.Add(new ListViewItem(new[]
                                                                    {
                                                                        set.SpawnInterval.ToString(),
                                                                        set.SpawnTotal.ToString()
                                                                    }));
            }
        }

        private void waveEnemySpawnSetsLv_SelectedIndexChanged(object sender, EventArgs e)
        {
            bool goodSelection = waveEnemySpawnSetsLv.SelectedIndices.Count > 0;

            waveSpawnSetGbx.Enabled = goodSelection;

            if (!goodSelection) return;

            int spawnSetIndex = waveEnemySpawnSetsLv.SelectedIndices[0];

            int waveIndex = configWavesLv.SelectedIndices[0];

            waveSpawnIntervalTxbx.Text = GameLevel.LevelWaves[waveIndex].EnemySets[spawnSetIndex].SpawnInterval.ToString();

            //waveSpawnTotalTxbx.Text = GameLevel.LevelWaves[waveIndex].EnemySets[spawnSetIndex].SpawnTotal.ToString();

            spawnSetEnemiesLv.Items.Clear();

            foreach (Enemy enemyType in GameLevel.LevelWaves[waveIndex].EnemySets[spawnSetIndex].Enemies)
            {
                //spawnSetEnemiesLv.Items.Add(new ListViewItem(new[]
                //                                                    {
                //                                                        enemyType.ID.ToString(),
                //                                                        enemyType.Stats.Hp.ToString(),
                //                                                        enemyType.Stats.Power.ToString(),
                //                                                        enemyType.Stats.Speed.ToString(),
                //                                                    }));
            }
        }

        private void levelWaveFormSaveMenuItem_Click(object sender, EventArgs e)
        {
            DialogResult = DialogResult.OK;
            Close();
        }

        private void addToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LevelWave lvlWave = new LevelWave { Id = GameLevel.LevelWaves.Count + 1 };
            GameLevel.LevelWaves.Add(lvlWave);
            configWavesLv.Items.Add(new ListViewItem(new[]
                                                         {
                                                             lvlWave.Id.ToString(),
                                                             lvlWave.StartTime.ToString(),
                                                             lvlWave.EnemySets.Count.ToString()
                                                         }));
        }

        private void waveStartTimeTxbx_TextChanged(object sender, EventArgs e)
        {
            try
            {
                int index = configWavesLv.SelectedIndices[0];
                float value = float.Parse(waveStartTimeTxbx.Text);
                GameLevel.LevelWaves[index].StartTime = value;
            }
            catch
            {
                MessageBox.Show(Resources.waveStartTimeWarning, Resources.LevelWavesFormTitle);
            }
        }

        private void waveAddSpawnSet_Click(object sender, EventArgs e)
        {
            if (configWavesLv.SelectedIndices.Count == 0)
                return;

            int index = configWavesLv.SelectedIndices[0];

            EnemySpawnSet spawnSet = new EnemySpawnSet();

            GameLevel.LevelWaves[index].EnemySets.Add(spawnSet);
            
            waveEnemySpawnSetsLv.Items.Add(new ListViewItem(new[]
                                                                {
                                                                    spawnSet.SpawnInterval.ToString(),
                                                                    spawnSet.SpawnTotal.ToString()
                                                                }));

            configWavesLv.Items[index].SubItems[2].Text = GameLevel.LevelWaves[index].EnemySets.Count.ToString();
        }

        private void spawnSetRemove_Click(object sender, EventArgs e)
        {
            if (waveEnemySpawnSetsLv.SelectedIndices.Count == 0)
                return;

            int waveIndex = configWavesLv.SelectedIndices[0];

            int enemySetIndex = waveEnemySpawnSetsLv.SelectedIndices[0];

            waveEnemySpawnSetsLv.Items.RemoveAt(enemySetIndex);

            GameLevel.LevelWaves[waveIndex].EnemySets.RemoveAt(enemySetIndex);

            configWavesLv.Items[waveIndex].SubItems[2].Text = GameLevel.LevelWaves[waveIndex].EnemySets.Count.ToString();
        }

        private void spawnMoveUp_Click(object sender, EventArgs e)
        {
            if (waveEnemySpawnSetsLv.SelectedIndices.Count == 0)
                return;

            int index = waveEnemySpawnSetsLv.SelectedIndices[0];

            ListViewItem lvItem = waveEnemySpawnSetsLv.Items[index];

            waveEnemySpawnSetsLv.Items.RemoveAt(index);

            int insertIndex = index - 1 <= 0 ? 0 : index - 1;

            waveEnemySpawnSetsLv.Items.Insert(insertIndex, lvItem);

            EnemySpawnSet spawnSet = GameLevel.LevelWaves[configWavesLv.SelectedIndices[0]].EnemySets[index];

            GameLevel.LevelWaves[configWavesLv.SelectedIndices[0]].EnemySets.RemoveAt(insertIndex);

            GameLevel.LevelWaves[configWavesLv.SelectedIndices[0]].EnemySets.Insert(insertIndex, spawnSet);
        }

        private void spawnSetMoveDown_Click(object sender, EventArgs e)
        {
            if (waveEnemySpawnSetsLv.SelectedIndices.Count == 0)
                return;

            int index = waveEnemySpawnSetsLv.SelectedIndices[0];

            ListViewItem lvItem = waveEnemySpawnSetsLv.Items[index];

            waveEnemySpawnSetsLv.Items.RemoveAt(index);

            waveEnemySpawnSetsLv.Items.Insert(index + 1, lvItem);

            EnemySpawnSet spawnSet = GameLevel.LevelWaves[configWavesLv.SelectedIndices[0]].EnemySets[index];

            GameLevel.LevelWaves[configWavesLv.SelectedIndices[0]].EnemySets.RemoveAt(index);

            GameLevel.LevelWaves[configWavesLv.SelectedIndices[0]].EnemySets.Insert(index + 1, spawnSet);
        }

        private void add1ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (configWavesLv.SelectedIndices.Count == 0 ||
                waveEnemySpawnSetsLv.SelectedIndices.Count == 0 ||
                levelObjLv.SelectedIndices.Count == 0)
            {
                return;
            }

            AddEnemiesToSet(1, levelObjLv.SelectedIndices[0]);
        }

        private void add3ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (configWavesLv.SelectedIndices.Count == 0 ||
                waveEnemySpawnSetsLv.SelectedIndices.Count == 0 ||
                levelObjLv.SelectedIndices.Count == 0)
            {
                return;
            }

            AddEnemiesToSet(3, levelObjLv.SelectedIndices[0]);
        }

        private void add5ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (configWavesLv.SelectedIndices.Count == 0 ||
                waveEnemySpawnSetsLv.SelectedIndices.Count == 0 ||
                levelObjLv.SelectedIndices.Count == 0)
            {
                return;
            }

            AddEnemiesToSet(5, levelObjLv.SelectedIndices[0]);
        }

        private void add10ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (configWavesLv.SelectedIndices.Count == 0 ||
                waveEnemySpawnSetsLv.SelectedIndices.Count == 0 ||
                levelObjLv.SelectedIndices.Count == 0)
            {
                return;
            }

            AddEnemiesToSet(10, levelObjLv.SelectedIndices[0]);
        }

        private void AddEnemiesToSet(int count, int enemyIndex)
        {
            for(int i = 0; i < count; ++i)
            {
                //spawnSetEnemiesLv.Items.Add(new ListViewItem(new[]
                //                                             {
                //                                                 Enemies[enemyIndex].ID.ToString(),
                //                                                 Enemies[enemyIndex].Stats.Hp.ToString(),
                //                                                 Enemies[enemyIndex].Stats.Power.ToString(),
                //                                                 Enemies[enemyIndex].Stats.Speed.ToString(),
                //                                             }));


                GameLevel.LevelWaves[configWavesLv.SelectedIndices[0]].EnemySets[waveEnemySpawnSetsLv.SelectedIndices[0]]
                    .Enemies.Add(Enemies[enemyIndex]);
            }
        }

        private void levelObjLv_MouseClick(object sender, MouseEventArgs e)
        {
            if(e.Button == MouseButtons.Right)
            {
                lvlObjCtxMenu.Show(levelObjLv, levelObjLv.PointToClient(Cursor.Position));
            }
        }

        private void spawnSetEnemiesLv_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                spawnEnemySetCtxMenu.Show(spawnSetEnemiesLv, spawnSetEnemiesLv.PointToClient(Cursor.Position));
            }
        }

        private void removeEnemyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (configWavesLv.SelectedIndices.Count == 0 ||
                waveEnemySpawnSetsLv.SelectedIndices.Count == 0)
            {
                return;
            }

            int waveIndex = configWavesLv.SelectedIndices[0];
            int setIndex = waveEnemySpawnSetsLv.SelectedIndices[0];
            int enemyIndex = spawnSetEnemiesLv.SelectedIndices[0];

            spawnSetEnemiesLv.Items.RemoveAt(enemyIndex);
            GameLevel.LevelWaves[waveIndex].EnemySets[setIndex].Enemies.RemoveAt(enemyIndex);
        }

        private void removeToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            if (configWavesLv.SelectedIndices.Count == 0 ||
                waveEnemySpawnSetsLv.SelectedIndices.Count == 0)
            {
                return;
            }

            int waveIndex = configWavesLv.SelectedIndices[0];
            int setIndex = waveEnemySpawnSetsLv.SelectedIndices[0];

            spawnSetEnemiesLv.Items.Clear();
            GameLevel.LevelWaves[waveIndex].EnemySets[setIndex].Enemies.Clear();
        }

        private void removeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (configWavesLv.SelectedIndices.Count == 0)
                return;
            int index = configWavesLv.SelectedIndices[0];
            configWavesLv.Items.RemoveAt(index);
            GameLevel.LevelWaves.RemoveAt(index);
        }

        private void lvlStartTimeTxbx_TextChanged(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(lvlStartTimeTxbx.Text))
            {
                MessageBox.Show(Resources.EmptyStartTimeWarning, Resources.LevelEditorTitle);
                return;
            }

            try
            {
                GameLevel.StartTime = float.Parse(lvlStartTimeTxbx.Text);
            }
            catch
            {
                MessageBox.Show(Resources.LevelStartTimeNumericValueWarning, Resources.LevelEditorTitle);
            }
        }

        private void levelObjLv_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (levelObjLv.SelectedIndices.Count == 0)
                return;

            editLvEnemyCanvas.Invalidate();
        }

        private void editLvEnemyCanvas_Paint(object sender, PaintEventArgs e)
        {
            if (levelObjLv.SelectedIndices.Count == 0)
                return;

            string imgSrc = Enemies[levelObjLv.SelectedIndices[0]].TextureName;

            if (string.IsNullOrEmpty(imgSrc))
                imgSrc = @"C:\Projects\Editor\Editor\Content\Icons\noImage.png";

            e.Graphics.DrawImage(Image.FromFile(imgSrc), editLvEnemyCanvas.ClientRectangle);
        }
    }
}